package edu.whu.rose.clock.ssql.index;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Date;

import com.sleepycat.je.DatabaseException;
import com.sleepycat.je.Environment;

import edu.whu.rose.clock.setup.IndexEnvironment;

public class EdgeInvertedList {

	//database
	private EdgeIndexDB idb;
	
	//cache
	private EdgeIndexCache ic;

	private String rowFile;
	private String columnFile;
	
	public EdgeInvertedList(Environment dbEnv) {
		idb = new EdgeIndexDB(dbEnv);
	}
	
	public EdgeInvertedList(Environment dbEnv, String dbName) {
		idb = new EdgeIndexDB(dbEnv, dbName);
	}
	
	public static void main(String[] args) {
		File file = new File("F:/data/dbEnv4");
		if (file.isDirectory()) {
			File[] files = file.listFiles();
			for (int i = 0; i < files.length; i++) {
				files[i].delete();
			}
		}
		
		RelationshipMatrix rm = new RelationshipMatrix(1754297);
		rm.fillDiagonalNodes();
		rm.load("graph/edge.txt");
		
		IndexEnvironment ie = new IndexEnvironment("F:/data/dbEnv4");
		if (!ie.openEnv()) {
			System.exit(1);
		}
		EdgeInvertedList eil = new EdgeInvertedList(ie.getEnvironment());
		eil.init();
		eil.setRowFile("F:/data/rows.txt");
		eil.setColumnFile("F:/data/columns.txt");
		
		Date startTime = new Date();
		eil.createIndex(rm);
		Date endTime = new Date();
		System.out.println("Completed indexing. The time spent is " + (endTime.getTime() - startTime.getTime()) + "ms");
		
		eil.close();
		ie.closeEnv();
	}
	
	public void init() {
		if (!idb.openDB()) {
			System.exit(1);
		}
		ic = new EdgeIndexCache(idb, 3000000);
	}
	
	public void close() {
		idb.closeDB();
	}
	
	
	public void createIndex(RelationshipMatrix rm) {
		Date sDate = new Date();
		Date eDate = null;
		
		try {
			BufferedReader rowReader = new BufferedReader(new FileReader(rowFile));
			BufferedReader columnReader = new BufferedReader(new FileReader(columnFile));
			int counter = 0;
			String line = null;
			while (rowReader.ready() && columnReader.ready()) {
				line = rowReader.readLine().trim();
				int row = rm.parseSN(line).intValue();
				line = columnReader.readLine().trim();
				int column = rm.parseSN(line).intValue();
				String[] paths = rm.power(row - 1, column - 1);
				this.insertEdge(row + "/" + column, paths);
				
				counter++;
				if (counter % 10000 == 0) {
					System.out.println(counter);
					eDate = new Date();
					System.out.println("Time exhausted: " + (eDate.getTime() - sDate.getTime()) + " ms");
					sDate = eDate;
				}
			}
			ic.flush();
		}
		catch (FileNotFoundException ex) {
			ex.printStackTrace();
		}
		catch (UnsupportedEncodingException ex) {
			ex.printStackTrace();
		}
		catch (IOException ex) {
			ex.printStackTrace();
		}
		catch (DatabaseException ex) {
			ex.printStackTrace();
		}
		ic.statistic();
		
//		HashMap<Integer,RelationshipNode> rowHeads = rm.getRowHeads();
//		Iterator<Integer> it = rowHeads.keySet().iterator();
//		while (it.hasNext()) {
//			Integer rowNum = it.next();
//			for (RelationshipNode rn = rowHeads.get(rowNum); rn != null; rn = rn.getNextNodeInSameRow()) {
//				String relationship = rn.getRelationship().trim();
//				if (relationship.length() > 0) {
//					String row = "" + rn.getRow();
//					String column = "" + rn.getColumn();
//					this.insertEdge(row + "/" + column, relationship);
//				}
//			}
//			System.out.println(rowNum.intValue());
//			eDate = new Date();
//			System.out.println("Time exhausted: " + (eDate.getTime() - sDate.getTime()) + " ms");
//			sDate = eDate;
//			ic.statistic();
//		}
//		try {
//			SequentialStrArray ssa = ic.getFromDB("write/incollection");
//			ic.flush();
//		}
//		catch (DatabaseException ex) {
//			ex.printStackTrace();
//		}
//		catch (UnsupportedEncodingException ex) {
//			ex.printStackTrace();
//		}
//		ic.statistic();
	}
	
	public void insertEdge(String key, String[] value) {
		for (int i = 0; i < value.length; i++) {
			String path = value[i].trim();
			if (path.length() > 0) {
				String[] edges = path.split("/");
				try {
					if (edges == null || edges.length > 3) {
						System.out.println("Found wrong path: " + path);
						continue;
					}
					if (edges.length > 0) {
						ic.initInsert(edges[0] + ">", key);
						if (edges.length > 1) {
							ic.initInsert(edges[0] + ">>", key);
							ic.initInsert(edges[1] + ">", key);
							ic.initInsert(">" + edges[1] + ">", key);
							ic.initInsert(edges[0] + ">" + edges[1] + ">", key);
							if (edges.length > 2) {
								ic.initInsert(edges[2], key);
								ic.initInsert(edges[1] + "/" + edges[2], key);
								ic.initInsert(edges[0] + "/" + edges[1] + "/" + edges[2], key);
								ic.initInsert(edges[0] + "//" + edges[2], key);
							}
						}
					}
				}
				catch (DatabaseException ex) {
					ex.printStackTrace();
				}
				catch (UnsupportedEncodingException ex) {
					ex.printStackTrace();
				}
			}
		}
	}

	public void setRowFile(String rowFile) {
		this.rowFile = rowFile;
	}

	public void setColumnFile(String columnFile) {
		this.columnFile = columnFile;
	}

}
